package org.xtremeobjects.domain.model.expression.ocl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.ocl.ParserException;
import org.eclipse.ocl.Query;
import org.eclipse.ocl.OCL;
import org.eclipse.ocl.ecore.Constraint;
import org.eclipse.ocl.expressions.OCLExpression;
import org.eclipse.ocl.helper.OCLHelper;


public class ExpressionEvaluator {
	
	public static void main(String[] args) {
		EcoreFactory ecoreFactory = org.eclipse.emf.ecore.EcoreFactory.eINSTANCE;
		EcorePackage ecorePackage = org.eclipse.emf.ecore.EcorePackage.eINSTANCE;
		EClass clazz = ecoreFactory.createEClass();
		clazz.setName("Teste");
		EAttribute name = ecoreFactory.createEAttribute();
		name.setName("name");
		name.setEType(ecorePackage.getEString());
		clazz.getEStructuralFeatures().add(name);
		EPackage pack = org.eclipse.emf.ecore.EcoreFactory.eINSTANCE.createEPackage();
		pack.setName("TestePackage");
		pack.setNsPrefix("TestePackage");
		pack.setNsURI("http://teste.com.br");
		pack.getEClassifiers().add(clazz);
		
		Map<EClass, Set<EObject>> extents = new HashMap<EClass, Set<EObject>>();
		Set<EObject> instances = new HashSet<EObject>();
		extents.put(clazz, instances);
		
		EObject obj;
		instances.add(obj=createTeste(clazz, "Juan"));
		instances.add(createTeste(clazz, "Camilla"));
		instances.add(createTeste(clazz, "Barbara"));
		instances.add(obj=createTeste(clazz, "Bruno"));
		
		
		
		Object ret = EvaluateExpression(new ArrayList(instances), clazz, "Teste.allInstances().name", extents );
		System.out.println(ret.toString());
		
	}

	private static EObject createTeste(EClass clazz, String nome) {
		EObject obj = clazz.getEPackage().getEFactoryInstance().create(clazz);
		obj.eSet(clazz.getEStructuralFeature("name"), nome);
		return obj;
	}

	static public Object EvaluateExpression(EObject obj, EClass eClass, String expression, Map<EClass, Set<EObject>> extents)
	{
		Object ret="";
		OCL<?, EClassifier, ?, ?, ?, ?, ?, ?, ?, Constraint, EClass, EObject> ocl = OCL.newInstance(org.eclipse.ocl.ecore.EcoreEnvironmentFactory.INSTANCE);
		OCLHelper<EClassifier, ?, ?, Constraint> helper = ocl.createOCLHelper();
		helper.setContext(eClass);
		try {
			OCLExpression<EClassifier> query = helper.createQuery(expression);
			Query<EClassifier, EClass, EObject> eval = ocl.createQuery( query );
			ocl.setExtentMap(extents);
			ret = eval.evaluate(obj);
		} catch (ParserException e) {
			e.printStackTrace();
		}
		
		return ret;
	}
	static public Object EvaluateExpression(List<?> obj, EClass eClass, String expression, Map<EClass, Set<EObject>> extents)
	{
		Object ret="";
		OCL<?, EClassifier, ?, ?, ?, ?, ?, ?, ?, Constraint, EClass, EObject> ocl = OCL.newInstance(org.eclipse.ocl.ecore.EcoreEnvironmentFactory.INSTANCE);
		OCLHelper<EClassifier, ?, ?, Constraint> helper = ocl.createOCLHelper();
		helper.setContext(eClass);
		try {
			OCLExpression<EClassifier> query = helper.createQuery(expression);
			Query<EClassifier, EClass, EObject> eval = ocl.createQuery( query );
			ocl.setExtentMap(extents);
			ret = eval.evaluate(obj);
		} catch (ParserException e) {
			e.printStackTrace();
		}
		
		return ret;
	}
}
